﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RPGProject.GameWorld;
using RPGProject.GameWorld.GameObjects;
using RPGProject.IOBuffers;
namespace RPGProject.LoopSystem
{
    class PlayerLoop : Loop
    {
        bool forceRender = false;
        private Visuals visuals;
        private World world;
        private Player player;
        private Constants c = Constants.GetInstance();
        public PlayerLoop(Visuals visuals, LoopManager loopManager, World world)
            : base (loopManager)
        {
            this.visuals = visuals;
            this.loopManager = loopManager;
            this.world = world;
            this.player = (Player)world["player"];
        }
        public override FuncType RunOnce()
        {
            if ((int)this.world["actionPoint"] == 0)
            {
                this.world["actionPoint"] = this.c["Player.ActionPoints"];
            }
            this.world.Render(forceRender);
            forceRender = false;
            // begin player turn

            String fullKey;
            String command = "";
            String parameter = "";
            int xmod = 0;
            int ymod = 0;
            fullKey = InputBuffer.ReadFormattedKey();
            // begin input translation
            if (fullKey == "D3")
            {
                Console.Write(" ");
                command = InputBuffer.ReadLine().Trim();
            }
            else
            {
                //begin fullkey switch statement
                ConvertKeyToCommand(fullKey, ref command, ref parameter);
                // end fullkey switch statement
            }
            // end input translation
            // begin command translation

            switch (command)
            {
                case "log":
                    this.visuals.ToShow = VisualType.LOG;
                    this.loopManager.AddFunc(FuncType.PRIORITY_TO_FRONT, this.visuals);
                    forceRender = true;
                    break;
                case "help":
                    this.visuals.ToShow = VisualType.HELP;
                    this.loopManager.AddFunc(FuncType.PRIORITY_TO_FRONT, this.visuals);
                    forceRender = true;
                    break;
                case "opening":
                    this.visuals.ToShow = VisualType.OPEN;
                    this.loopManager.AddFunc(FuncType.PRIORITY_TO_FRONT, this.visuals);
                    forceRender = true;
                    break;
                case "move":
                    GameObjectEvent moveEvent = this.player.GetMoveEvent();
                    ConvertDirToInt(parameter, ref xmod, ref ymod);
                    moveEvent["xmod"] = xmod;
                    moveEvent["ymod"] = ymod;
                    this.world.Listen(moveEvent);
                    this.world["actionPoint"] = (int)this.world["actionPoint"] - 1;
                    break;
                case "quit":
                    this.loopManager.ClearAllFuncs();
                    this.visuals.ToShow = VisualType.LOSE;
                    this.loopManager.AddFunc(FuncType.PRIORITY_TO_FRONT, this.visuals);
                    return FuncType.REPEAT;
                case "attack":
                    do
                    {
                        fullKey = InputBuffer.ReadFormattedKey();
                        parameter = ConvertKeyToDir(fullKey, parameter);
                    } while (parameter == "repeat");
                    ConvertDirToInt(parameter, ref xmod, ref ymod);
                    char angle;
                    switch (parameter)
                    {
                        case "left":
                        case "right":
                            angle = '-';
                            break;
                        case "up":
                        case "down":
                            angle = '|';
                            break;
                        case "downleft":
                        case "upright":
                            angle = '/';
                            break;
                        case "downright":
                        case "upleft":
                            angle = '\\';
                            break;
                        default:
                            angle = '@';
                            break;
                    }
                    Projectile bullet = new Projectile((int)this.player["x"], (int)this.player["y"], angle, xmod, ymod, this.c["Player.RangedDamage"], this.c["Player.Range"], "a bullet", this.player, this.world);
                    bullet.Init();
                    this.loopManager.AddFunc(FuncType.PRIORITY_TO_FRONT, new ProjectileLooper(bullet, this.loopManager));
                    this.world["actionPoint"] = (int)this.world["actionPoint"] - 1;
                    break;
                default:
                    break;
            }
            // end command translation
            // end player turn
            if ((int)this.world["actionPoint"] == 0)
                return FuncType.ADD_TO_END;
            else
                return FuncType.REPEAT;
        }

        /// <summary>
        /// Converts a key to a command and parameter.
        /// </summary>
        /// <param name="fullKey"></param>
        /// <param name="command"></param>
        /// <param name="parameter"></param>
        private static void ConvertKeyToCommand(String fullKey, ref String command, ref String parameter)
        {
            command = "";
            parameter = "";
            switch (fullKey)
            {
                case "numpad1":
                    command = "move";
                    parameter = "downleft";
                    break;
                case "numpad2":
                    command = "move";
                    parameter = "down";
                    break;
                case "numpad3":
                    command = "move";
                    parameter = "downright";
                    break;
                case "numpad4":
                    command = "move";
                    parameter = "left";
                    break;
                case "numpad6":
                    command = "move";
                    parameter = "right";
                    break;
                case "numpad7":
                    command = "move";
                    parameter = "upleft";
                    break;
                case "numpad8":
                    command = "move";
                    parameter = "up";
                    break;
                case "numpad9":
                    command = "move";
                    parameter = "upright";
                    break;
                case "leftarrow":
                    command = "move";
                    parameter = "left";
                    break;
                case "rightarrow":
                    command = "move";
                    parameter = "right";
                    break;
                case "uparrow":
                    command = "move";
                    parameter = "up";
                    break;
                case "downarrow":
                    command = "move";
                    parameter = "down";
                    break;
                case "q":
                    command = "quit";
                    break;
                case "l":
                    command = "log";
                    break;
                case "h":
                    command = "help";
                    break;
                case "o":
                    command = "opening";
                    break;
                case "a":
                    command = "attack";
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// Converts a key to a direction.
        /// </summary>
        /// <param name="fullKey"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private static String ConvertKeyToDir(String fullKey, String parameter)
        {
            parameter = "";
            switch (fullKey)
            {
                case "numpad1":
                    parameter = "downleft";
                    break;
                case "numpad3":
                    parameter = "downright";
                    break;
                case "numpad7":
                    parameter = "upleft";
                    break;
                case "numpad9":
                    parameter = "upright";
                    break;
                case "numpad4":
                case "leftarrow":
                    parameter = "left";
                    break;
                case "numpad6":
                case "rightarrow":
                    parameter = "right";
                    break;
                case "numpad8":
                case "uparrow":
                    parameter = "up";
                    break;
                case "numpad2":
                case "downarrow":
                    parameter = "down";
                    break;
                default:
                    parameter = "repeat";
                    break;
            }
            return parameter;
        }
        /// <summary>
        /// Converts a direction into an x and y vector.
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="xmod"></param>
        /// <param name="ymod"></param>
        private static void ConvertDirToInt(String parameter, ref int xmod, ref int ymod)
        {
            switch (parameter)
            {
                case "upleft":
                    xmod = -1;
                    ymod = -1;
                    break;
                case "upright":
                    xmod = 1;
                    ymod = -1;
                    break;
                case "downleft":
                    xmod = -1;
                    ymod = 1;
                    break;
                case "downright":
                    xmod = 1;
                    ymod = 1;
                    break;
                case "left":
                    ymod = 0;
                    xmod = -1;
                    break;
                case "up":
                    xmod = 0;
                    ymod = -1;
                    break;
                case "right":
                    xmod = 1;
                    ymod = 0;
                    break;
                case "down":
                    xmod = 0;
                    ymod = 1;
                    break;

            }
        }
        public override string ToString()
        {
            return "Player";
        }
    }
}
